using System;
using NodaTime.Utility;
using ServiceStack.Text;

namespace NodaTime.Serialization.ServiceStackText
{
    public class ComplexJsonIntervalSerializer : IServiceStackSerializer<Interval>
    {
        private IServiceStackSerializer<Instant> instantSerializer;

        public bool UseRawSerializer
        {
            get { return true; }
        }

        public ComplexJsonIntervalSerializer(IServiceStackSerializer<Instant> instantSerializer)
        {
            if (instantSerializer == null)
            {
                throw new ArgumentNullException("instantSerializer");
            }
            this.instantSerializer = instantSerializer;
        }

        public string Serialize(Interval value)
        {
            var complexIntervalDto = new ComplexRawIntervalDto
            {
                Start = instantSerializer.Serialize(value.Start),
                End = instantSerializer.Serialize(value.End)
            };

            return JsonSerializer.SerializeToString(complexIntervalDto);
        }

        public Interval Deserialize(string text)
        {
            var complexIntervalDto = JsonSerializer.DeserializeFromString<ComplexRawIntervalDto>(text);

            if (!IsValid(complexIntervalDto))
            {
                throw new InvalidNodaDataException("An Interval must contain Start and End properties.");
            }

            var start = instantSerializer.Deserialize(complexIntervalDto.Start);
            var end = instantSerializer.Deserialize(complexIntervalDto.End);

            var interval = new Interval(start, end);
            
            return interval;
        }

        private static bool IsValid(ComplexRawIntervalDto complexIntervalDto)
        {
            if (complexIntervalDto == null)
            {
                return false;
            }
            if (string.IsNullOrEmpty(complexIntervalDto.Start))
            {
                return false;
            }
            return !string.IsNullOrEmpty(complexIntervalDto.End);
        }
    }
}